package com.ds.core.shiro;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;

import com.ds.core.util.WebUtil;
import com.ds.orm.model.Permission;
import com.ds.orm.model.SysSession;
import com.ds.orm.model.User;
import com.ds.service.SysAuthorizeService;
import com.ds.service.SysSessionService;
import com.ds.service.UserService;

/**
 * 创建时间：2017年11月19日 上午11:42:08 项目名称：ds-sys-web
 * 
 * @author Du
 * @version 1.0
 * @since JDK 1.7 文件名称：Realm.java 类说明：
 */
public class Realm extends AuthorizingRealm {
	private final Logger logger = LogManager.getLogger();
	@Autowired
	private UserService userService;
	@Autowired
	SysAuthorizeService sysAuthorizeService;
	@Autowired
	private SysSessionService sysSessionService;
	@Autowired
	private RedisOperationsSessionRepository sessionRepository;

	// 权限
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		long userId = WebUtil.getCurrentUser();
		// 根据用户id获得角色，权限集合
		Set<String> roles = sysAuthorizeService.getRoleTypesByUserId(userId);
		Set<Permission> permissions = sysAuthorizeService.queryPermissionsByUserId(userId);
		info.addRoles(roles);
		for (Permission permission : permissions) {
			info.addStringPermission(permission.getUrl());
		}
		return info;
	}

	// 登录验证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
			throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		StringBuilder pswd = new StringBuilder(100);
		for (int i = 0; i < token.getPassword().length; i++) {
			pswd.append(token.getPassword()[i]);
		}
		User user = userService.normalLogin(token.getUsername(), pswd.toString());
		if (user == null) {
			logger.warn("USER [{}] PASSWORD IS WRONG: {}", token.getUsername(), pswd.toString());
			throw new AccountException("帐号或密码不正确！");
		}
		if (user.getEnable() != 1) {
			logger.warn("Account Disabled: {}", token.getUsername());
			throw new DisabledAccountException("账号已被禁用");
		}
		WebUtil.saveCurrentUser(user.getId());
		saveSession(user.getAccount());
		// 更新登录时间 last login time
		user.setLastLoginTime(new Date());
		userService.update(user);

		AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getAccount(), user.getPassword(), getName());
		System.out.println(getName() + "------Realm");
		return authcInfo;
	}

	/**
	 * 指定principalCollection 清除
	 */
	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
		super.clearCachedAuthorizationInfo(principals);
	}

	/** 保存session */
	private void saveSession(String account) {
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		// 踢出用户
		SysSession record = new SysSession();
		record.setAccount(account);
		List<?> sessionIds = sysSessionService.querySessionIdByAccount(record);
		if (sessionIds != null) {
			for (Object sessionId : sessionIds) {
				record.setSessionId((String) sessionId);
				sysSessionService.deleteBySessionId(record);
				if (!session.getId().equals(sessionId)) {
					sessionRepository.delete((String) sessionId);
					sessionRepository.cleanupExpiredSessions();
				}
			}
		}
		record.setSessionId(session.getId().toString());
		String host = (String) session.getAttribute("HOST");
		record.setIp(StringUtils.isBlank(host) ? session.getHost() : host);
		record.setStartTime(session.getStartTimestamp());
		sysSessionService.update(record);
	}
}
